/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.transitionseverywhere;

import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorGroup;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.Text;
import ohos.agp.components.TextField;
import ohos.agp.utils.Color;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

import java.util.Map;
/**
 * This transition tracks changes to the text in TextView targets. If the text
 * changes between the start and end scenes, the transition ensures that the
 * starting text stays until the transition ends, at which point it changes
 * to the end text.  This is useful in situations where you want to resize a
 * text view to its new size before displaying the text that goes there.
 */
public class ChangeText extends Transition {

    private static final String LOG_TAG = "TextChange";
    private static final HiLogLabel LABEL = new HiLogLabel(3, 0xD000F00, "[ChangeTextSample] ");

    private static final String PROPNAME_TEXT = "harmony:textchange:text";
    private static final String PROPNAME_TEXT_SELECTION_START =
            "harmony:textchange:textSelectionStart";
    private static final String PROPNAME_TEXT_SELECTION_END =
            "harmony:textchange:textSelectionEnd";
    private static final String PROPNAME_TEXT_COLOR = "harmony:textchange:textColor";
    private static boolean mSecondText;

    private int mChangeBehavior = CHANGE_BEHAVIOR_KEEP;

    /**
     * Flag specifying that the text in affected/changing TextView targets will keep
     * their original text during the transition, setting it to the final text when
     * the transition ends. This is the default behavior.
     *
     * @see #setChangeBehavior(int)
     */
    public static final int CHANGE_BEHAVIOR_KEEP = 0;
    /**
     * Flag specifying that the text changing animation should first fade
     * out the original text completely. The new text is set on the target
     * view at the end of the fade-out animation. This transition is typically
     * used with a later {@link #CHANGE_BEHAVIOR_IN} transition, allowing more
     * flexibility than the {@link #CHANGE_BEHAVIOR_OUT_IN} by allowing other
     * transitions to be run sequentially or in parallel with these fades.
     *
     * @see #setChangeBehavior(int)
     */
    public static final int CHANGE_BEHAVIOR_OUT = 1;
    /**
     * Flag specifying that the text changing animation should fade in the
     * end text into the affected target view(s). This transition is typically
     * used in conjunction with an earlier {@link #CHANGE_BEHAVIOR_OUT}
     * transition, possibly with other transitions running as well, such as
     * a sequence to fade out, then resize the view, then fade in.
     *
     * @see #setChangeBehavior(int)
     */
    public static final int CHANGE_BEHAVIOR_IN = 2;
    /**
     * Flag specifying that the text changing animation should first fade
     * out the original text completely and then fade in the
     * new text.
     *
     * @see #setChangeBehavior(int)
     */
    public static final int CHANGE_BEHAVIOR_OUT_IN = 3;

    private static final String[] sTransitionProperties = {
            PROPNAME_TEXT,
            PROPNAME_TEXT_SELECTION_START,
            PROPNAME_TEXT_SELECTION_END
    };
    /**
     * Sets the type of changing animation that will be run, one of
     * {@link #CHANGE_BEHAVIOR_KEEP}, {@link #CHANGE_BEHAVIOR_OUT},
     * {@link #CHANGE_BEHAVIOR_IN}, and {@link #CHANGE_BEHAVIOR_OUT_IN}.
     *
     * @param changeBehavior The type of fading animation to use when this
     *                       transition is run.
     * @return this textChange object.
     */
    public ChangeText setChangeBehavior(int changeBehavior) {
        if (changeBehavior >= CHANGE_BEHAVIOR_KEEP && changeBehavior <= CHANGE_BEHAVIOR_OUT_IN) {
            mChangeBehavior = changeBehavior;
        }
        return this;
    }

    @Override
    public String[] getTransitionProperties() {
        return sTransitionProperties;
    }

    /**
     * Returns the type of changing animation that will be run.
     *
     * @return either {@link #CHANGE_BEHAVIOR_KEEP}, {@link #CHANGE_BEHAVIOR_OUT},
     * {@link #CHANGE_BEHAVIOR_IN}, or {@link #CHANGE_BEHAVIOR_OUT_IN}.
     */
    public int getChangeBehavior() {
        return mChangeBehavior;
    }

    String TEXT_1 = "Hi, i am text. Tap on me!";
    String TEXT_2 = "Thanks! Another tap?";
    private void captureValues(TransitionValues transitionValues) {
        if (transitionValues.view instanceof Text) {
            Text textView = (Text) transitionValues.view;
            mSecondText = !mSecondText;
            transitionValues.values.put(PROPNAME_TEXT,mSecondText ? TEXT_2 : TEXT_1);
            if (textView instanceof TextField) {
            }
            if (mChangeBehavior > CHANGE_BEHAVIOR_KEEP) {
                transitionValues.values.put(PROPNAME_TEXT_COLOR, mSecondText ? Color.RED : Color.BLUE);
            }
        }
    }

    @Override
    public void captureStartValues(TransitionValues transitionValues) {
        if (transitionValues.view instanceof Text) {
            Text textView = (Text) transitionValues.view;
            transitionValues.values.put(PROPNAME_TEXT, textView.getText());
            if (mChangeBehavior > CHANGE_BEHAVIOR_KEEP) {
                transitionValues.values.put(PROPNAME_TEXT_COLOR, textView.getTextColor());
            }
        }
    }

    @Override
    public void captureEndValues(TransitionValues transitionValues) {
        captureValues(transitionValues);
    }

    @Override
    public Animator createAnimator(ComponentContainer sceneRoot, TransitionValues startValues,
                                   TransitionValues endValues) {
        if (startValues == null || endValues == null ||
                !(startValues.view instanceof Text) || !(endValues.view instanceof Text)) {
            return null;
        }
        final Text view = (Text) endValues.view;
        Map<String, Object> startVals = startValues.values;
        Map<String, Object> endVals = endValues.values;
        final CharSequence startText = startVals.get(PROPNAME_TEXT) != null ?
                (CharSequence) startVals.get(PROPNAME_TEXT) : "";
        final CharSequence endText = endVals.get(PROPNAME_TEXT) != null ?
                (CharSequence) endVals.get(PROPNAME_TEXT) : "";
        final int startSelectionStart, startSelectionEnd, endSelectionStart, endSelectionEnd;
        if (view instanceof TextField) {
            startSelectionStart = startVals.get(PROPNAME_TEXT_SELECTION_START) != null ?
                    (Integer) startVals.get(PROPNAME_TEXT_SELECTION_START) : -1;
            startSelectionEnd = startVals.get(PROPNAME_TEXT_SELECTION_END) != null ?
                    (Integer) startVals.get(PROPNAME_TEXT_SELECTION_END) : startSelectionStart;
            endSelectionStart = endVals.get(PROPNAME_TEXT_SELECTION_START) != null ?
                    (Integer) endVals.get(PROPNAME_TEXT_SELECTION_START) : -1;
            endSelectionEnd = endVals.get(PROPNAME_TEXT_SELECTION_END) != null ?
                    (Integer) endVals.get(PROPNAME_TEXT_SELECTION_END) : endSelectionStart;
        } else {
            startSelectionStart = startSelectionEnd = endSelectionStart = endSelectionEnd = -1;
        }
        if (!startText.equals(endText)) {
            final int startColor;
            final int endColor;
            if (mChangeBehavior != CHANGE_BEHAVIOR_IN) {
                view.setText(String.valueOf(startText));
                if (view instanceof TextField) {
                    setSelection(((TextField) view), startSelectionStart, startSelectionEnd);
                }
            }
            Animator anim;
            if (mChangeBehavior == CHANGE_BEHAVIOR_KEEP) {
                startColor = endColor = 0;
                //anim = AnimatorValue.ofFloat(0, 1);
                anim = new AnimatorValue();
                ((AnimatorValue) anim).setStateChangedListener(new Animator.StateChangedListener() {

                    @Override
                    public void onStart(Animator animator) {

                    }

                    @Override
                    public void onStop(Animator animator) {
                    }

                    @Override
                    public void onCancel(Animator animator) {

                    }

                    @Override
                    public void onEnd(Animator animator) {
                        if (startText.equals(view.getText())) {
                            // Only set if it hasn't been changed since anim started
                            view.setText(String.valueOf(endText));
                            if (view instanceof TextField) {
                                setSelection(((TextField) view), endSelectionStart, endSelectionEnd);
                            }
                        }
                    }

                    @Override
                    public void onPause(Animator animator) {

                    }

                    @Override
                    public void onResume(Animator animator) {

                    }

                });
            } else {
                startColor = ((Color)startVals.get(PROPNAME_TEXT_COLOR)).getValue();
                endColor = ((Color)endVals.get(PROPNAME_TEXT_COLOR)).getValue();
                // Fade out start text
                AnimatorValue outAnim = null, inAnim = null;
                if (mChangeBehavior == CHANGE_BEHAVIOR_OUT_IN ||
                        mChangeBehavior == CHANGE_BEHAVIOR_OUT) {
                    outAnim = new AnimatorValue();
                    outAnim.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
                        @Override
                        public void onUpdate(AnimatorValue animatorValue, float v) {
                            view.setAlpha(Float.valueOf(1) -v);
                        }
                    });

                    outAnim.setStateChangedListener(new Animator.StateChangedListener() {
                        @Override
                        public void onStart(Animator animator) {

                        }

                        @Override
                        public void onStop(Animator animator) {

                        }

                        @Override
                        public void onCancel(Animator animator) {

                        }

                        @Override
                        public void onEnd(Animator animator) {
                            if (startText.equals(view.getText())) {
                                // Only set if it hasn't been changed since anim started
                                view.setText(String.valueOf(endText));
                                if (view instanceof TextField) {
                                    setSelection(((TextField) view), endSelectionStart,
                                            endSelectionEnd);
                                }
                            }
                            // restore opaque alpha and correct end color
                            view.setTextColor(new Color(endColor));
                        }

                        @Override
                        public void onPause(Animator animator) {

                        }

                        @Override
                        public void onResume(Animator animator) {

                        }
                    });
                }
                if (mChangeBehavior == CHANGE_BEHAVIOR_OUT_IN ||
                        mChangeBehavior == CHANGE_BEHAVIOR_IN) {
                    inAnim = new AnimatorValue();
                    inAnim.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
                        @Override
                        public void onUpdate(AnimatorValue animatorValue, float v) {
                            view.setAlpha(v);

                        }
                    });
                    inAnim.setStateChangedListener(new Animator.StateChangedListener() {
                        @Override
                        public void onStart(Animator animator) {

                        }

                        @Override
                        public void onStop(Animator animator) {

                        }

                        @Override
                        public void onCancel(Animator animator) {
                            view.setTextColor(new Color(endColor));
                        }

                        @Override
                        public void onEnd(Animator animator) {

                        }

                        @Override
                        public void onPause(Animator animator) {

                        }

                        @Override
                        public void onResume(Animator animator) {

                        }
                    });

                }
                if (outAnim != null && inAnim != null) {
                    anim = new AnimatorGroup();
                    ((AnimatorGroup) anim).runSerially(outAnim, inAnim);
                } else if (outAnim != null) {
                    anim = outAnim;
                } else {
                    // Must be an in-only animation
                    anim = inAnim;
                }
            }
            TransitionListener transitionListener = new TransitionListenerAdapter() {
                int mPausedColor = 0;

                @Override
                public void onTransitionPause(Transition transition) {
                    HiLog.info(LABEL, "onAnimation Pause: inside ChangeText Listener for transitionListener");
                    if (mChangeBehavior != CHANGE_BEHAVIOR_IN) {
                        view.setText(String.valueOf(endText));
                        if (view instanceof TextField) {
                            setSelection(((TextField) view), endSelectionStart, endSelectionEnd);
                        }
                    }
                    if (mChangeBehavior > CHANGE_BEHAVIOR_KEEP) {
                        mPausedColor = view.getTextColor().getValue();
                        view.setTextColor(new Color(endColor));
                    }
                }

                @Override
                public void onTransitionResume(Transition transition) {
                    if (mChangeBehavior != CHANGE_BEHAVIOR_IN) {
                        view.setText(String.valueOf(startText));
                        if (view instanceof TextField) {
                            setSelection(((TextField) view), startSelectionStart, startSelectionEnd);
                        }
                    }
                    if (mChangeBehavior > CHANGE_BEHAVIOR_KEEP) {
                        view.setTextColor(new Color(mPausedColor));
                    }
                }

                @Override
                public void onTransitionEnd(Transition transition) {
                    transition.removeListener(this);
                }
            };
            addListener(transitionListener);
            return anim;
        }
        return null;
    }

    private void setSelection(TextField editText, int start, int end) {
        if (start >= 0 && end >= 0) {
        }
    }
}
